﻿namespace Home.Services.OptimizationServices
{
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Http;
    using System.Web.OData;
    using System.Web.OData.Query;
    using System.Web.OData.Routing;
    using Home.Data;
    using Home.Models;
    using Home.Repository;

    [ServiceHandleError(ServiceName = WebsiteServiceHelper.OptimizationODataServiceName)]
    public class OptimizationController : BaseODataController
    {
        private readonly OptimizationDbContext database = new OptimizationDbContext();

        #region Comment operations

        [RequestValidation(RequestType = RequestType.Optimization)]
        [HttpGet]
        [EnableQuery(PageSize = 500)]
        [ODataRoute("Comments")]
        public IHttpActionResult GetComments(ODataQueryOptions<OptimizationComment> options)
        {
            var entities = this.database.Comments.AsQueryable();
            return Ok(entities);
        }

        [RequestValidation(RequestType = RequestType.Optimization)]
        [HttpGet]
        [ODataRoute("Comments({id})")]
        public Task<IHttpActionResult> GetComment([FromODataUri] Guid id, ODataQueryOptions<OptimizationComment> options)
        {
            var entities = this.database.Comments.Where(s => s.Id == id);
            return GetODataSingleAsync(entities, options);
        }

        [HttpPost]
        [ODataRoute("Comments")]
        public async Task<IHttpActionResult> PostComment(OptimizationComment entity)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            // TODO: add registered user ID
            return Created(await CreateAsync(entity));
        }

        #endregion

        #region Visit operations

        [RequestValidation(RequestType = RequestType.Optimization)]
        [HttpGet]
        [EnableQuery(PageSize = 500)]
        [ODataRoute("Visits")]
        public IHttpActionResult GetVisits(ODataQueryOptions<OptimizationVisit> options)
        {
            var entities = this.database.Visits.AsQueryable();
            return Ok(entities);
        }

        [RequestValidation(RequestType = RequestType.Optimization)]
        [HttpGet]
        [ODataRoute("Visits({id})")]
        public Task<IHttpActionResult> GetVisit([FromODataUri] Guid id, ODataQueryOptions<OptimizationVisit> options)
        {
            var entities = this.database.Visits.Where(s => s.Id == id);
            return GetODataSingleAsync(entities, options);
        }

        [HttpPost]
        [ODataRoute("Visits")]
        public async Task<IHttpActionResult> PostVisit(OptimizationVisit entity)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            // TODO: add registered user ID
            return Created(await CreateAsync(entity));
        }

        #endregion

        #region Common actions

        [RequestValidation(RequestType = RequestType.Optimization)]
        [HttpPost]
        [ODataRoute("Remove()")]
        public async Task<IHttpActionResult> Remove(ODataActionParameters parameters)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var category = (OptimizationCategory)parameters["category"];
            var time = (DateTimeOffset)parameters["time"];

            if (!Enum.IsDefined(typeof(OptimizationCategory), category))
            {
                return BadRequest("The category is invalid.");
            }

            if (time > DateTimeOffset.UtcNow)
            {
                return BadRequest("The time is invalid.");
            }

            var sql = default(string);
            switch (category)
            {
                case OptimizationCategory.Comment:
                    sql = "DELETE t_optimization_visitor_comment WHERE [created] <= {0}";
                    break;
                case OptimizationCategory.Visit:
                    sql = "DELETE t_optimization_visitor_visit WHERE [created] <= {0}";
                    break;
            }

            await this.database.Database.ExecuteSqlCommandAsync(sql, time);

            return Ok();
        }

        #endregion

        #region Comment helpers

        private async Task<OptimizationComment> CreateAsync(OptimizationComment entity)
        {
            var now = DateTimeOffset.UtcNow;
            var user = Thread.CurrentPrincipal.Identity.Name;

            entity.Create(this.database.Comments, now, user, true);

            await this.database.SaveChangesAsync();
            return entity;
        }

        #endregion

        #region Visit helpers

        private async Task<OptimizationVisit> CreateAsync(OptimizationVisit entity)
        {
            var now = DateTimeOffset.UtcNow;
            var user = Thread.CurrentPrincipal.Identity.Name;

            entity.Create(this.database.Visits, now, user, true);

            await this.database.SaveChangesAsync();
            return entity;
        }

        #endregion

        #region Helpers

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                this.database.Dispose();
            }

            base.Dispose(disposing);
        }

        #endregion
    }
}